﻿using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.Networking;

namespace XFABManager
{
    public class UpdateOrDownloadResRequest : CustomAsyncOperation<UpdateOrDownloadResRequest>
    {

        /// <summary>
        /// 下载速度 单位:字节
        /// </summary>
        public long CurrentSpeed { get; protected set; }

        /// <summary>
        /// 格式化之后的下载速度
        /// </summary>
        public string CurrentSpeedFormatStr { get; protected set; } = string.Empty;

        /// <summary>
        /// 已下载的文件大小
        /// </summary>
        public long DownloadedSize { get; private set; }

        /// <summary>
        /// 需要下载的大小
        /// </summary>
        public long NeedDownloadedSize { get; private set; }

        internal IEnumerator UpdateOrDownloadRes(string projectName) {
            if (!AssetBundleManager.isInited)
            {
                // 初始化
                yield return AssetBundleManager.InitializeAsync();
            }

            CheckResUpdateRequest requestUpdate = AssetBundleManager.CheckResUpdate(projectName);
            yield return requestUpdate;

            if ( !string.IsNullOrEmpty( requestUpdate.error ) ) {
                Completed(requestUpdate.error);
                yield break;
            }
            yield return CoroutineStarter.Start(UpdateOrDownloadRes(requestUpdate.result));
        }

        /// <summary>
        /// 更新或下载资源
        /// </summary>
        /// <param name="result"></param>
        /// <returns></returns>
        internal IEnumerator UpdateOrDownloadRes(CheckUpdateResult result) {

            NeedDownloadedSize = result.updateSize;

            if (!AssetBundleManager.isInited)
            {
                // 初始化
                yield return AssetBundleManager.InitializeAsync();
            }

            // 判断是不是下载 压缩包
            if (result.updateType == UpdateType.DownloadZip)
            {
                string zipUrl = XFABTools.ServerPath(AssetBundleManager.GetProfile(result.projectName).url, result.projectName, result.version, string.Format("{0}.zip", result.projectName) );
                string zip_md5_url = XFABTools.ServerPath(AssetBundleManager.GetProfile(result.projectName).url, result.projectName, result.version, string.Format("{0}_md5.txt", result.projectName));
                string localfile = XFABTools.LocalResPath(result.projectName, string.Format("{0}{1}", result.projectName, ".zip"));

                DownloadFileRequest requestZip = DownloadFileRequest.Download(zipUrl, localfile);
                //DownloadFileRequest requestZip = new DownloadFileRequest();
                //CoroutineStarter.Start(requestZip.Download(zipUrl, localfile));
                while ( !requestZip.isDone ) {
                    yield return null;
                    progress = requestZip.progress;
                    CurrentSpeed = requestZip.Speed;
                    DownloadedSize = requestZip.DownloadedSize;
                    //CurrentSpeedFormatStr = requestZip.CurrentSpeedFormatStr;
                }
                if (!string.IsNullOrEmpty(requestZip.error)) {
                    Completed(requestZip.error);
                    yield break; 
                }


                // 请求md5
                UnityWebRequest request_zip_md5 = UnityWebRequest.Get(zip_md5_url);
                request_zip_md5.timeout = 5;
                yield return request_zip_md5.SendWebRequest();

                string md5 = null;

#if UNITY_2020_1_OR_NEWER
                if (request_zip_md5.result != UnityWebRequest.Result.Success)
#else
                if (request_zip_md5.isNetworkError || request_zip_md5.isHttpError)
#endif
                {
                    error = request_zip_md5.error;
                    Completed(request_zip_md5.error);
                    yield break;
                }
                else 
                    md5 = request_zip_md5.downloadHandler.text;



                // 解压之前先校验文件是否正确
                FileMD5Request request_local_zip_md5 = XFABTools.CaculateFileMD5(localfile);
                while (!request_local_zip_md5.isDone)
                {
                    yield return null;
                }

                if (!string.IsNullOrEmpty(request_local_zip_md5.error))
                {
                    Completed(request_local_zip_md5.error);
                    yield break;
                }

                if (!md5.Equals(request_local_zip_md5.md5)) {
                    // md5 校验失败
                    File.Delete(localfile); // 删除本地的文件
                    Completed("md5校验失败!");
                    yield break;
                }


                try
                { 
                    // 进行解压
                    ZipTools.UnZipFile(localfile, XFABTools.DataPath(result.projectName));
                }
                catch (System.Exception e)
                {
                    Debug.LogErrorFormat("解压出错:{0} error:{1}", localfile, e.ToString());
                }
                // 解压完成之后 删除压缩包
                File.Delete(localfile);
            }
            else if(result.updateType == UpdateType.Update || result.updateType == UpdateType.Download)
            {
                // 更新下载
                string fileUrl = null;
                string localFile = null;

                //Dictionary<string, string> files = new Dictionary<string, string>();
                List<DownloadObjectInfo> files = new List<DownloadObjectInfo>();

                ProjectBuildInfo local_build_info = XFABTools.LocalProjectBuildInfo(result.projectName);

                for (int i = 0; i < result.need_update_bundles.Length; i++)
                {
                    fileUrl = XFABTools.ServerPath(AssetBundleManager.GetProfile(result.projectName).url, result.projectName, result.version, result.need_update_bundles[i].bundleName);// 这个文件名是包含后缀的
                    localFile = XFABTools.LocalResPath(result.projectName, result.need_update_bundles[i].bundleName);

                    //requestFiles.Add(fileUrl, localFile);

                    files.Add( new DownloadObjectInfo( fileUrl, localFile, result.need_update_bundles[i].bundleSize));
                }
                DownloadFilesRequest requestFiles = DownloadFilesRequest.DownloadFiles(files);

                List<FileMD5Request> all_verify_res_request = new List<FileMD5Request>(); // 保存所有的校验中的资源

                requestFiles.onFileDownloadCompleted += (info) => {
                    // 校验和更新资源
                    string bundleName = System.IO.Path.GetFileName(info.localfile);
                    if (bundleName.Equals(XFABConst.project_build_info)) {
                        local_build_info.Copy(XFABTools.LocalProjectBuildInfo(result.projectName));
                        local_build_info.Save();
                    }
                    BundleInfo bundleInfo = null;
                    foreach (var item in result.need_update_bundles)
                    {
                        if (item.bundleName.Equals(bundleName))
                            bundleInfo = item;
                    }

                    if (bundleInfo != null) {
                        // 计算本地的md5
                        FileMD5Request request = XFABTools.CaculateFileMD5(info.localfile);
                        request.completed += (response) => {

                            if (response.md5.Equals(bundleInfo.md5))
                            {
                                // 文件校验通过 更新配置
                                local_build_info.UpdateBundleFile(bundleInfo.bundleName, bundleInfo.bundleSize, bundleInfo.md5);
                            }
                            else {
                                // 文件校验失败 移除配置
                                local_build_info.RemoveBundleFile(bundleInfo.bundleName);
                            } 
                        };
                        all_verify_res_request.Add(request);
                    }

                };

                //CoroutineStarter.Start(requestFiles.Download());
                while (  !requestFiles.isDone)
                {
                    yield return null;
                    progress = requestFiles.progress;
                    CurrentSpeed = requestFiles.Speed;
                    DownloadedSize = requestFiles.DownloadedSize;
                    //CurrentSpeedFormatStr = requestFiles.CurrentSpeedFormatStr;
                }

                if ( !string.IsNullOrEmpty(requestFiles.error) )
                {
                    Completed(requestFiles.error/*, requestFiles.file_url*/);
                    yield break;
                }

                // 等待所有的校验完成
                foreach (var item in all_verify_res_request)
                {
                    while ( !item.isDone )
                        yield return null;
                }

                // 验证下载的资源是否正确 
                CheckResUpdateRequest requestUpdate = AssetBundleManager.CheckResUpdate(result.projectName);
                yield return requestUpdate;

                // 验证出错
                if (!string.IsNullOrEmpty(requestUpdate.error))
                {
                    Completed(requestUpdate.error);
                    yield break;
                }

                if ( requestUpdate.result.updateType != UpdateType.DontNeedUpdate ) {
                    // 说明资源不匹配 需要重新下载
                    Completed(string.Format("资源校验失败,请稍后重试!"));
                    yield break;
                } 
            }

            // 保存 Version
            XFABTools.SaveVersion(result.projectName, result.version);

            // 下载完成
            Completed();

        }

    }

}

